]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
Add a hack to block calls to certain introspected functions
authorDan Winship <danw@gnome.org>
Fri, 26 Mar 2010 20:38:03 +0000 (16:38 -0400)
committerDan Winship <danw@gnome.org>
Thu, 20 May 2010 19:49:16 +0000 (15:49 -0400)
This is useful for keeping people from using methods that only fail in
certain circumstances, by making them fail in all circumstances
instead.

https://bugzilla.gnome.org/show_bug.cgi?id=618918

js/ui/environment.js
src/shell-global.c
src/shell-global.h

index 209cdc82277d3d6d6be8a0c71b7324cb5c8c66bf..67682d8fe0e225e5ca63d31761c8f9e0b85a2ab0 100644 (file)
@@ -1,5 +1,6 @@
 /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
+const Shell = imports.gi.Shell;
 const St = imports.gi.St;
 const Gettext_gtk20 = imports.gettext.domain('gtk20');
 
@@ -28,8 +29,34 @@ function _patchContainerClass(containerClass) {
     };
 }
 
-_patchContainerClass(St.BoxLayout);
-_patchContainerClass(St.Table);
+// Replace @method with something that throws an error instead
+function _blockMethod(method, replacement, reason) {
+    let match = method.match(/^(.+)\.([^.]+)$/);
+    if (!match)
+        throw new Error('Bad method name "' + method + '"');
+    let proto = 'imports.gi.' + match[1] + '.prototype';
+    let property = match[2];
+
+    if (!global.set_property_mutable(proto, property, true))
+        throw new Error('Bad method name "' + method + '"');
+
+    // eval() is evil in general, but we know it's safe here since
+    // set_property_mutable() would have failed if proto was
+    // malformed.
+    let node = eval(proto);
+
+    let msg = 'Do not use "' + method + '".';
+    if (replacement)
+        msg += ' Use "' + replacement + '" instead.';
+    if (reason)
+        msg += ' (' + reason + ')';
+
+    node[property] = function() {
+        throw new Error(msg);
+    };
+
+    global.set_property_mutable(proto, property, false);
+}
 
 function init() {
     Tweener.init();
@@ -39,4 +66,20 @@ function init() {
     if (Gettext_gtk20.gettext('default:LTR') == 'default:RTL') {
         St.Widget.set_default_direction(St.TextDirection.RTL);
     }
+
+    _patchContainerClass(St.BoxLayout);
+    _patchContainerClass(St.Table);
+
+    _blockMethod('Clutter.Event.get_state', 'Shell.get_event_state',
+                 'gjs\'s handling of Clutter.ModifierType is broken. See bug 597292.');
+    _blockMethod('Gdk.Display.get_pointer', 'global.get_pointer',
+                 'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
+    _blockMethod('Gdk.Window.get_pointer', 'global.get_pointer',
+                 'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
+
+    // Now close the back door to prevent extensions from trying to
+    // abuse it. We can't actually delete it since
+    // Shell.Global.prototype itself is read-only.
+    global.set_property_mutable('imports.gi.Shell.Global.prototype', 'set_property_mutable', true);
+    Shell.Global.prototype.set_property_mutable = undefined;
 }
index 758af542e891349678a266b3f41a8d0ba617025e..5d61e41e2d069bd9d4a14a1a3935c80ae9ae2d47 100644 (file)
@@ -1327,3 +1327,68 @@ shell_global_create_app_launch_context (ShellGlobal *global)
 
   return (GAppLaunchContext *)context;
 }
+
+/**
+ * shell_global_set_property_mutable:
+ * @global: the #ShellGlobal
+ * @object: the "path" to a JS object, starting from the root object.
+ *  (Eg, "global.stage" or "imports.gi.Gtk.Window.prototype")
+ * @property: a property on @object
+ * @mutable: %TRUE or %FALSE
+ *
+ * If @mutable is %TRUE, this clears the "permanent" and "readonly" flags
+ * on @property of @object. If @mutable is %FALSE, it sets them.
+ *
+ * You can use this to make it possible to modify properties that
+ * would otherwise be read-only from JavaScript.
+ *
+ * Return value: success or failure.
+ */
+gboolean
+shell_global_set_property_mutable (ShellGlobal *global,
+                                   const char  *object,
+                                   const char  *property,
+                                   gboolean     mutable)
+{
+  JSContext *context = gjs_context_get_native_context (global->js_context);
+  char **parts;
+  JSObject *obj;
+  jsval val = JSVAL_VOID;
+  int i;
+  jsuint attrs;
+  JSBool found;
+
+  JS_AddRoot (context, &val);
+
+  parts = g_strsplit (object, ".", -1);
+  obj = JS_GetGlobalObject (context);
+  for (i = 0; parts[i]; i++)
+    {
+      if (!JS_GetProperty (context, obj, parts[i], &val))
+        {
+          g_strfreev (parts);
+          JS_RemoveRoot (context, &val);
+          gjs_log_exception (context, NULL);
+          return FALSE;
+        }
+      obj = JSVAL_TO_OBJECT (val);
+    }
+  g_strfreev (parts);
+
+  if (!JS_GetPropertyAttributes (context, obj, property, &attrs, &found) || !found)
+    {
+      JS_RemoveRoot (context, &val);
+      gjs_log_exception (context, NULL);
+      return FALSE;
+    }
+
+  if (mutable)
+    attrs &= ~(JSPROP_PERMANENT | JSPROP_READONLY);
+  else
+    attrs |= (JSPROP_PERMANENT | JSPROP_READONLY);
+
+  JS_SetPropertyAttributes (context, obj, property, attrs, &found);
+
+  JS_RemoveRoot (context, &val);
+  return !gjs_log_exception (context, NULL);
+}
index 5ac31d820ff01adcd71c25197e0571db0c0a8f1f..27c43be97fb2d30d4095465615a4613c800f8f26 100644 (file)
@@ -96,6 +96,11 @@ guint32 shell_global_get_current_time (ShellGlobal *global);
 
 GAppLaunchContext *shell_global_create_app_launch_context (ShellGlobal *global);
 
+gboolean shell_global_set_property_mutable (ShellGlobal *global,
+                                            const char  *object,
+                                            const char  *property,
+                                            gboolean     mutable);
+
 G_END_DECLS
 
 #endif /* __SHELL_GLOBAL_H__ */